package com.syjy.tunnelworker.senders.iml;

import com.alibaba.fastjson.JSON;

import com.syjy.DataExchangeException;
import com.syjy.container.ProtocolDataContainer;
import com.syjy.tunnelinfo.BaseTunnelInfo;
import com.syjy.tunnelinfo.DataPoint;
import com.syjy.tunnelworker.BaseProtocolTunnel;
import com.syjy.tunnelworker.senders.DataSenderInterface;
import lombok.Getter;
import lombok.Setter;
import wei.yigulu.modbus.domain.ModbusSlaveDataContainer;
import wei.yigulu.modbus.domain.datatype.BooleanModbusDataInRegister;
import wei.yigulu.modbus.domain.datatype.ModbusDataTypeEnum;
import wei.yigulu.modbus.domain.datatype.NumericModbusData;
import wei.yigulu.netty.BaseProtocolBuilder;

import java.math.BigDecimal;
import java.util.*;

/**
 * 抽象的modbus数据获取
 *
 * @author: xiuwei
 * @version:
 */
@Setter
@Getter
public abstract class AbstractModbusDataSender<T extends BaseTunnelInfo, E extends BaseProtocolBuilder> extends BaseProtocolTunnel<T,E> implements DataSenderInterface {

  protected E protocolBuilder;
  /**
   * 通道点位  ---- 点位对象
   */
  Map<Integer, DataPoint> dataPointMap;


  /**
   * 通道点位 遥信点位  ---- 点位对象
   */
  Map<Integer, DataPoint> yxDataPoints=new HashMap<>();

  /**
   * 通道点位 遥测点位  ---- 点位对象
   */
  Map<Integer, DataPoint> ycDataPoints=new HashMap<>();

  ModbusSlaveDataContainer modbusSlaveDataContainer;
  Integer slaveId;
  /**
   * 0: 线圈   1：寄存器
   */
  private int functionFlag;


  /**
   * 顶层的构造方法
   *
   * @param tunnelInfo 通道信息
   */
  public AbstractModbusDataSender(T tunnelInfo) {
    super(tunnelInfo);
  }

  @Override
  public void updateData2Protocol() throws DataExchangeException {
    HashMap<Integer, String> dataMap = new HashMap<>();
    if (functionFlag == 1) {
      dataPointMap.forEach((k, v) -> {
        if (ModbusDataTypeEnum.A16 == v.getDataType() && dataPointMap.containsKey(v.getId())) {
          BooleanModbusDataInRegister booleanModbusDataInRegister = new BooleanModbusDataInRegister();
          Boolean bValue = ProtocolDataContainer.getInstance().getBoolean(v.getId());
          dataMap.put(k, bValue.toString());
          booleanModbusDataInRegister.setValue(0, bValue);
          modbusSlaveDataContainer.setRegister(slaveId, k, booleanModbusDataInRegister);
        } else if (ModbusDataTypeEnum.A16 != v.getDataType() && ycDataPoints.containsKey(v.getId())) {
          Number nValue = BigDecimal.valueOf(ProtocolDataContainer.getInstance().getNumber(v.getId()).doubleValue());
          dataMap.put(k, nValue.toString());
          modbusSlaveDataContainer.setRegister(slaveId, k, ((NumericModbusData) (v.getDataType().getObject())).setValue(BigDecimal.valueOf(nValue.doubleValue())));
        }
      });
    } else {
      dataPointMap.forEach((k, v) ->
        {
          if (yxDataPoints.containsKey(v.getId())) {
            Boolean bValue ;
            bValue = ProtocolDataContainer.getInstance().getBoolean(v.getId());
            dataMap.put(k, bValue.toString());
            modbusSlaveDataContainer.setCoil(slaveId, k, bValue);
          }
        }
      );
    }
    log.info(JSON.toJSONString(dataMap));
  }


  @Override
  public void parseGatherDataPoint() throws DataExchangeException {
    this.log.info("解析该通道下所管理的点位");
    List<DataPoint> dataPoints = this.tunnelInfo.getDataPoints();
    Map<Integer, DataPoint> dataPointMap = new HashMap<>();
    if (dataPoints == null || dataPoints.size() == 0) {
      this.dataPointMap = dataPointMap;
      return;
    }
    Collections.sort(dataPoints, Comparator.comparingInt(DataPoint::getProtocolPoint));
    int i = 0;
    for (DataPoint d : dataPoints) {
      dataPointMap.put(i, d);
      if (d.getDataType() == ModbusDataTypeEnum.A16) {
        yxDataPoints.put(d.getId(), d);
      } else {
        ycDataPoints.put(d.getId(),d);
      }
      i += d.getDataType().getOccupiedRegister();
    }
    this.dataPointMap = dataPointMap;
    this.log.info("解析该通道下所管理的点位完成");
  }
}
